package com.usian.service;

import com.github.pagehelper.PageHelper;
import com.usian.mapper.SearchItemMapper;
import com.usian.pojo.SearchItem;
import com.usian.utils.JsonUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class SearchItemServiceImpl implements SearchItemService {
    @Autowired
    private SearchItemMapper searchItemMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Value("${ES_INDEX_NAME}")
    private String ES_INDEX_NAME;
    @Value("${ES_TYPE_NAME}")
    private String ES_TYPE_NAME;


    @Override
    public void importAll() {

        try {
            GetIndexRequest getIndexRequest = new GetIndexRequest();
            GetIndexRequest indices = getIndexRequest.indices(ES_INDEX_NAME);
            boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
            if (!exists) {
                CreateIndexRequest createIndexRequest = new CreateIndexRequest(ES_INDEX_NAME);
                createIndexRequest.settings(Settings.builder().put("number_of_shards", 2)
                        .put("number_of_replicas", 1));
                createIndexRequest.mapping(ES_TYPE_NAME, "{\n" +
                        "  \"_source\": {\n" +
                        "    \"excludes\": [\n" +
                        "      \"item_desc\"\n" +
                        "    ]\n" +
                        "  },\n" +
                        "  \"properties\": {\n" +
                        "    \"item_title\": {\n" +
                        "      \"type\": \"text\",\n" +
                        "      \"analyzer\": \"ik_max_word\",\n" +
                        "      \"search_analyzer\": \"ik_smart\"\n" +
                        "    },\n" +
                        "    \"item_sell_point\": {\n" +
                        "      \"type\": \"text\",\n" +
                        "      \"analyzer\": \"ik_max_word\",\n" +
                        "      \"search_analyzer\": \"ik_smart\"\n" +
                        "    },\n" +
                        "    \"item_price\": {\n" +
                        "      \"type\": \"float\"\n" +
                        "    },\n" +
                        "    \"item_image\": {\n" +
                        "      \"type\": \"text\",\n" +
                        "      \"index\": false\n" +
                        "    },\n" +
                        "    \"item_category_name\": {\n" +
                        "      \"type\": \"keyword\"\n" +
                        "    },\n" +
                        "    \"item_desc\": {\n" +
                        "      \"type\": \"text\",\n" +
                        "      \"analyzer\": \"ik_max_word\",\n" +
                        "      \"search_analyzer\": \"ik_smart\"\n" +
                        "    }\n" +
                        "  }\n" +
                        "}", XContentType.JSON);
                IndicesClient indices1 = restHighLevelClient.indices();
                CreateIndexResponse createIndexResponse = indices1.create(createIndexRequest, RequestOptions.DEFAULT);
            }

            int page = 1;
            while (true) {

                PageHelper.startPage(page, 1000);
                List<SearchItem> esDocumentList = searchItemMapper.getItemList();
                if (esDocumentList.size() == 0) {
                    break;
                }
                BulkRequest bulkRequest = new BulkRequest();
                for (SearchItem searchItem : esDocumentList) {
                    bulkRequest.add(new IndexRequest(ES_INDEX_NAME, ES_TYPE_NAME,searchItem.getId()).
                            source(JsonUtils.objectToJson(searchItem), XContentType.JSON));


                }
                restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                page++;

            }


        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    @Override
    public List<SearchItem> selectByQ(String q, Integer page, Integer pagesize) {

        try {
            SearchRequest searchRequest = new SearchRequest(ES_INDEX_NAME).types(ES_TYPE_NAME);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(q, "item_title","item_desc","item_sell_point","item_category_name"));
            searchSourceBuilder.from((page - 1) * pagesize);
            searchSourceBuilder.size(pagesize);
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.preTags("<font color='red'>");
            highlightBuilder.postTags("</font>");
            highlightBuilder.field("item_title");

            searchSourceBuilder.highlighter(highlightBuilder);


            searchRequest.source(searchSourceBuilder);
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = search.getHits();
            List<SearchItem>list=new ArrayList<>();
            for (SearchHit hit : hits) {
                SearchItem searchItem = JsonUtils.jsonToPojo(hit.getSourceAsString(), SearchItem.class);
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                if(highlightFields!=null && highlightFields.size()>0) {
                    searchItem.setItem_title(highlightFields.get("item_title").
                            getFragments()[0].toString());
                }
                list.add(searchItem);

            }
            return list;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }

    @Override
    public int insertDocument(String msg) {

        // 1、根据商品id查询商品信息。
        SearchItem searchItem = searchItemMapper.getItemById(Long.valueOf(msg));

        //2、添加商品到索引库
        IndexRequest indexRequest = new IndexRequest(ES_INDEX_NAME, ES_TYPE_NAME);
        indexRequest.source(JsonUtils.objectToJson(searchItem), XContentType.JSON);
        IndexResponse indexResponse =
                null;
        try {
            indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return indexResponse.getShardInfo().getFailed();
    }
}
